﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using ExaminationSys.DataAccess.Repository;

namespace ExaminationSys.DataAccess
{
    public abstract class Singleton<T> where T : class
    {
        private static readonly Lazy<T> _instance
            = new Lazy<T>(() =>
                              {
                                  var ctors = typeof(T).GetConstructors(
                                      BindingFlags.Instance
                                      | BindingFlags.NonPublic
                                      | BindingFlags.Public);
                                  if (ctors.Count() != 1)
                                      throw new InvalidOperationException(
                                          String.Format("Type {0} must have exactly one constructor.", typeof(T)));
                                  var ctor = ctors.SingleOrDefault(c => c.GetParameters().Count() == 0 && c.IsPrivate);
                                  if (ctor == null)
                                      throw new InvalidOperationException(
                                          String.Format(
                                              "The constructor for {0} must be private and take no parameters.",
                                              typeof(T)));
                                  return (T)ctor.Invoke(null);
                              });

        public static T Instance
        {
            get { return _instance.Value; }
        }
    }

    public sealed class ObjectFactory<TService>
    {
        private static ConcurrentDictionary<string, TService> dicts =
            new ConcurrentDictionary<string, TService>();

        public static TService Create()
        {
            var type = typeof(TService);
            TService t;
            if (dicts.TryGetValue(type.Name, out t))
            {
                return t;
            }

            var factoryType = Type.GetType(string.Format("ExaminationSys.DataAccess.{0}Factory", type.Name));

            if (factoryType == null)
                throw new Exception(string.Format("not found {0}Factory class", type.Name));

            //var pi = factoryType.GetProperties(
            //    BindingFlags.Static | BindingFlags.FlattenHierarchy |
            //    BindingFlags.CreateInstance |
            //    BindingFlags.Public |
            //    BindingFlags.NonPublic).Where(p => p.Name.Equals("Instance")).FirstOrDefault();

            //if (pi == null) return default(TService);
            var result =
                Expression.Lambda<Func<TService>>(
                    Expression.Property(null,
                                        factoryType,
                                        "Instance"))
                    .Compile()
                    .Invoke();

            //var property = Expression.Property(null, pi, null);
            //var result = Expression.Lambda<Func<TService>>(property).Compile().Invoke();
            if (result != null)
            {
                dicts.TryAdd(type.Name, result);
            }
            return result;
        }
    }

    public class NewsTypeServiceFactory : Singleton<NewsTypeService>
    {
    }

    public class NewsServiceFactory : Singleton<NewsService>
    {
    }
    public class Sys_DictionaryServiceFactory : Singleton<Sys_DictionaryService>
    {
    }

    public class Sys_UserServiceFactory : Singleton<Sys_UserService>
    {
    }

    public class SubSectionInfoServiceFactory : Singleton<SubSectionInfoService>
    {
    }

    public class SubSectionDetailInfoServiceFactory : Singleton<SubSectionDetailInfoService>
    {
    }

    public class SectionTypeServiceFactory : Singleton<SectionTypeService>
    {
    }

    public class SectionInfoServiceFactory : Singleton<SectionInfoService>
    {
    }

    public class SectionLinkServiceFactory : Singleton<SectionLinkService>
    {
    }

    public class SectionPaperServiceFactory : Singleton<SectionPaperService>
    {
    }

    public class SectionInformationServiceFactory : Singleton<SectionInformationService>
    {
    }

    public class SectionDownloadServiceFactory : Singleton<SectionDownloadService>
    {
    }
    public class PaperFeedBackCommentServiceFactory : Singleton<PaperFeedBackCommentService>
    {
    }
    public class PaperFeedbackServiceFactory : Singleton<PaperFeedbackService>
    {
    }

    public class StudentServiceFactory : Singleton<StudentService>
    {
    }

    public class TeacherInfoServiceFactory : Singleton<TeacherInfoService>
    {
    }

    public class PaperInfoServiceFactory : Singleton<PaperInfoService>
    {
    }

    public class PaperDetailAutoServiceFactory : Singleton<PaperDetailAutoService>
    {
    }

    public class PaperSubjectQuestionServiceFactory : Singleton<PaperSubjectQuestionService>
    {
    }

    public class DBQuestionServiceFactory : Singleton<DBQuestionService>
    {
    }

    public class DBSubjectServiceFactory : Singleton<DBSubjectService>
    {
    }

    public class DBSubjectQuestionServiceFactory : Singleton<DBSubjectQuestionService>
    {
    }

    public class DBAnswerServiceFactory : Singleton<DBAnswerService>
    {
    }

    public class StudentTestHistoryServiceFactory : Singleton<StudentTestHistoryService>
    {
    }

    public class StudentTestQuestionServiceFactory : Singleton<StudentTestQuestionService>
    {
    }

    public class LoginLogServiceFactory:Singleton<LoginLogService>{}

    public class StudentLevelServiceFactory : Singleton<StudentLevelService> { }

    public class StudentRankServiceFactory:Singleton<StudentRankService>{}

    public class TeacherPrivilegeRelServiceFactory:Singleton<TeacherPrivilegeRelService>{}
}
